package com.example.java_gobang.api;

import com.example.java_gobang.game.MatchRequest;
import com.example.java_gobang.game.MatchResponse;
import com.example.java_gobang.game.Matcher;
import com.example.java_gobang.game.OnlineUserManager;
import com.example.java_gobang.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

//通过这个类处理匹配功能的 websocket 请求
@Component
@Slf4j
public class MatchAPI extends TextWebSocketHandler {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private Matcher matcher;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线，将在线信息保存起来
        //1.获取到当前用户的身份信息，因为我们添加了握手拦截器
        // 注意，如果用户之前没有通过http进行登录，直接访问game_hall.html，此时就会出现user为空的情况
        User user = (User)session.getAttributes().get("user");
        if(user == null){
            MatchResponse matchResponse = new MatchResponse();
            matchResponse.setOk(false);
            matchResponse.setReason("你尚未登录，不能进行后续匹配");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(matchResponse)));
            return;
        }
        WebSocketSession webSocketSession = onlineUserManager.getFromGameHall(user.getUserId());
        WebSocketSession webSocketSession1 = onlineUserManager.getFromGameRoom(user.getUserId());
        if(webSocketSession != null || webSocketSession1 != null){
            //用户已经登录
            MatchResponse matchResponse = new MatchResponse();
            matchResponse.setOk(false);
            matchResponse.setReason("您已经在别处登录了");
            matchResponse.setMessage("repeatConnection");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(matchResponse)));
            //这里直接关闭有点太激进了，针对这个情况返回特殊的message供客户端进行控制
//                session.close();//关闭连接，该方法会触发afterConnectionClosed，需要注意不要把原有的账号下线
            return;
        }
        onlineUserManager.enterGameHall(user.getUserId(), session);
        log.info("玩家" + user.getUsername() + "进入游戏大厅");

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //处理开始匹配和停止匹配请求
        User user = (User)session.getAttributes().get("user");
        String payLoad = message.getPayload();//获取数据载荷
        //当前这个数据载荷是一个Json格式的字符串，需要转化为Java对象
        MatchRequest request = objectMapper.readValue(payLoad, MatchRequest.class);
        MatchResponse response = new MatchResponse();
        if(request.getMessage().equals("startMatch")){
            //进入匹配队列
            log.info("玩家" + user.getUsername() + " 进入匹配队列......");
            matcher.add(user);
            response.setOk(true);
            response.setMessage("startMatch");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        } else if (request.getMessage().equals("stopMatch")){
            log.info("玩家" + user.getUsername() + " 退出匹配队列......");
            matcher.remove(user);
            response.setOk(true);
            response.setMessage("stopMatch");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        } else {
            //非法情况
            log.warn("服务端收到了非法的websocket请求：" + request.getMessage());
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        //玩家下线
        //为了避免因为多开问题导致的异常下线，我们判断当前session是否在onlineUserManager中维护
        //如果没有维护就不做操作了
        User user = (User)session.getAttributes().get("user");
        if(user == null)
            return;
        matcher.remove(user);
        WebSocketSession webSocketSession = onlineUserManager.getFromGameHall(user.getUserId());
        //要保证维护的session是一个session才下线
        if(webSocketSession == session)
            onlineUserManager.existGameHall(user.getUserId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //玩家下线
        //为了避免因为多开问题导致的异常下线，我们判断当前session是否在onlineUserManager中维护
        //如果没有维护就不做操作了
        User user = (User)session.getAttributes().get("user");
        if(user == null)
            return;
        matcher.remove(user);
        WebSocketSession webSocketSession = onlineUserManager.getFromGameHall(user.getUserId());
        //要保证维护的session是一个session才下线
        if(webSocketSession == session)
            onlineUserManager.existGameHall(user.getUserId());
    }
}
